package com.ww.springboot.boot.util;

import cn.hutool.core.util.ObjectUtil;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author : wanwei
 * 工具类目前只能适用于预报场景,其他场景可能不兼容
 * @date : 2020/11/18 19:34
 */
public class AutoBuildReq {


	private static <T> T buildObject(Class<?> clazz, Map<String, Object> map) {
		try {
			T o = (T) clazz.newInstance();
			cycle(clazz, o, 0, map);
			return o;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private static void cycle(Class<?> clazz, Object o, Integer index, Map<String, Object> map) throws IllegalAccessException, InstantiationException {
		//获取类属性
		Field[] declaredFieldsSon = clazz.getDeclaredFields();
		for (Field fieldSon : declaredFieldsSon) {
			Class<?> type = fieldSon.getType();
			fieldSon.setAccessible(true);
			//判断类是否list
			if (type == List.class) {
				Class<?> actualType = (Class<?>) ((ParameterizedTypeImpl) fieldSon.getGenericType()).getActualTypeArguments()[0];
				//将新对象赋值给所属类
				List<Object> list = new ArrayList<>();
				fieldSon.set(o, list);
				AutoMap annotation = fieldSon.getAnnotation(AutoMap.class);
				//获取list对象size
				Integer size = getListSize(annotation.entity(), map);
				for (int i = 0; i < size; i++) {
					Object o1 = actualType.newInstance();
					list.add(o1);
					cycle(actualType, o1, i, map);
				}
			} else {
				//具体字段 进行赋值
				//非具体字段 则说明还需要继续往下层遍历
				if (!type.getName().contains("com.zhkj.forecast")) {
					//判断是否包含 @autoMap
					AutoMap annotation = fieldSon.getAnnotation(AutoMap.class);
					if (annotation == null) {
						continue;
					}
					Object mapValue = null;
					//从映射中取值
					if (ObjectUtil.isNotEmpty(annotation.entity())
						&& ObjectUtil.isNotEmpty(annotation.column())) {
						mapValue = getValue(annotation.entity(), annotation.column()[0], index, map);
					}
					//取默认值
					if (ObjectUtil.isEmpty(mapValue) && ObjectUtil.isNotEmpty(annotation.defaultValue())) {
						mapValue = annotation.defaultValue();
					}
					//为空则不处理
					if(mapValue == null){
						continue;
					}
					//根据字段类型赋值 避免类型不一致抛异常(后续继续补充)
					switch (fieldSon.getType().getName()) {
						case "java.lang.String":
							fieldSon.set(o, String.valueOf(mapValue));
							break;
						case "java.math.BigDecimal":
							fieldSon.set(o, new BigDecimal(String.valueOf(mapValue)));
							break;
						default:
					}
					continue;
				}
				//创建对象
				Object o1 = type.newInstance();
				//将新对象赋值给所属类
				fieldSon.set(o, o1);

				cycle(type, o1, index, map);
			}
		}
	}

	private static Object getValue(String first, String secondKey, int index, Map<String, Object> map) {
		Object firstMap = map.get(first);
		if (firstMap == null) {
			throw new RuntimeException("首层映射" + first + "不存在!");
		}
		if (firstMap instanceof Map) {
			return ((Map<String, Object>) firstMap).get(secondKey);
		}
		if (firstMap instanceof List) {
			return ((List<Map<String, Object>>) firstMap).get(index).get(secondKey);
		}
		throw new RuntimeException(first + "-" + secondKey + " 映射关系异常!");
	}

	private static Integer getListSize(String first, Map<String, Object> map) {
		Object firstMap = map.get(first);
		if (firstMap == null) {
			throw new RuntimeException("首层映射" + first + "不存在!");
		}
		if (firstMap instanceof List) {
			return ((List<Map<String, Object>>) firstMap).size();
		}
		throw new RuntimeException(first + " 映射关系异常!");
	}


//	public static void main(String[] args) {
//		OrderEntityBO orderEntityBO = new OrderEntityBO();
//		OrderEntity orderEntity = new OrderEntity();
//		orderEntity.setCode("code");
//		orderEntityBO.setOrder(orderEntity);
//
//		List<OrderGoodsEntity> list = new ArrayList<>();
//		for (int i = 0; i < 5; i++) {
//			OrderGoodsEntity orderGoodsEntity = new OrderGoodsEntity();
//			orderGoodsEntity.setNameEn("nameEn" + i);
//			list.add(orderGoodsEntity);
//		}
//		orderEntityBO.setGoods(list);
//
//		SanTProperties sanTProperties = new SanTProperties();
//		sanTProperties.setAppKey("appKey");
//		sanTProperties.setToken("token");
//		sanTProperties.setUserId("userId");
//
//		SanTrackNoReq object = AutoBuildReq.autoBuild(orderEntityBO, sanTProperties, SanTrackNoReq.class);
//		System.out.println(JsonUtil.toJson(object));
//		System.out.println(object);
//	}
}
